#include <cinttypes>
#include <iostream>
#include <functional>
#include <variant>

using namespace std;

#define PRINTFUN_ADDR std::cout << static_cast<const char *>(__PRETTY_FUNCTION__) << " at " << this << std::endl

class A{
    int m_a = 1;
    int m_b = 2;
    int m_c = 3;
    uint8_t m_d = 4;
public:
    A(int a, int b, int c, uint8_t d);
    A();
    A& operator=(const A & other);
    A(A&& rhs) = delete;
    A& operator=(A&& rhs) = default;
    A(const A& rhs):
    m_a(rhs.m_a),
    m_b(rhs.m_b),
    m_c(rhs.m_c),
    m_d(rhs.m_d)
    {
        PRINTFUN_ADDR;
    }
    virtual ~A() { PRINTFUN_ADDR; };
    void Dump();
    void DoSomething()
    {
        cout << "Something" << endl;
    }
};

void A::Dump()
{
     using namespace std;
     auto dumpItem = [this](auto name, auto& item){
        std::cout << name << "@" << (void*)&item << ", value is " << item <<  ", size is " << sizeof(item) << endl;
     };
     dumpItem("m_a", m_a);
     dumpItem("m_b", m_b);
     dumpItem("m_c", m_c);
     dumpItem("m_d", m_d);
     cout << "Obj address:" << sizeof(*this) << endl;
}

A::A(int a, int b, int c, uint8_t d):
m_a(a),
m_b(b),
m_c(c)
{
    PRINTFUN_ADDR;
}

A::A()
{
    PRINTFUN_ADDR;
}

A& A::operator=(const A & other)
{
    m_a = other.m_a;
    m_b = other.m_b;
    m_c = other.m_c;
    m_d = other.m_d;
    return *this;
}

class B : public A{
    int m_bm = 3;
};

void Func(A item)
{
    item.DoSomething();
}



int main()
{
    cout << "start show" << endl;
    
    // A a{1,2,3,4};
    // cout << ">>>>" << __LINE__ << endl; 
    // Func(a); // A{5,6,7,8}.Dump();
    // A{5,6,7,8}.Dump();
    // cout << "<<<<<" << __LINE__ << endl;

    A a{};
    B b{};
    a = b;
    A * pa = new B{};
    delete pa;
    cout << "ending..." << endl;
}